package com.alipay.demo.trade.service.impl;

import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.request.AlipayTradePayRequest;
import com.alipay.api.response.AlipayTradeCancelResponse;
import com.alipay.api.response.AlipayTradePayResponse;
import com.alipay.api.response.AlipayTradeQueryResponse;
import com.alipay.demo.trade.config.Configs;
import com.alipay.demo.trade.model.TradeStatus;
import com.alipay.demo.trade.model.builder.AlipayTradePayContentBuilder;
import com.alipay.demo.trade.model.result.AlipayF2FPayResult;
import com.alipay.demo.trade.service.impl.AbsAlipayTradeService;
import org.apache.commons.lang3.StringUtils;

public class AlipayTradeServiceImpl extends AbsAlipayTradeService {

   public AlipayTradeServiceImpl(AlipayTradeServiceImpl.ClientBuilder builder) {
      if(StringUtils.isEmpty(builder.getGatewayUrl())) {
         throw new NullPointerException("gatewayUrl should not be NULL!");
      } else if(StringUtils.isEmpty(builder.getAppid())) {
         throw new NullPointerException("appid should not be NULL!");
      } else if(StringUtils.isEmpty(builder.getPrivateKey())) {
         throw new NullPointerException("privateKey should not be NULL!");
      } else if(StringUtils.isEmpty(builder.getFormat())) {
         throw new NullPointerException("format should not be NULL!");
      } else if(StringUtils.isEmpty(builder.getCharset())) {
         throw new NullPointerException("charset should not be NULL!");
      } else if(StringUtils.isEmpty(builder.getAlipayPublicKey())) {
         throw new NullPointerException("alipayPublicKey should not be NULL!");
      } else {
         this.client = new DefaultAlipayClient(builder.getGatewayUrl(), builder.getAppid(), builder.getPrivateKey(), builder.getFormat(), builder.getCharset(), builder.getAlipayPublicKey());
      }
   }

   public AlipayF2FPayResult tradePay(AlipayTradePayContentBuilder builder) {
      this.validateBuilder(builder);
      String outTradeNo = builder.getOutTradeNo();
      AlipayTradePayRequest request = new AlipayTradePayRequest();
      request.setBizContent(builder.toJsonString());
      this.log.info("trade.pay bizContent:" + request.getBizContent());
      AlipayTradePayResponse response = (AlipayTradePayResponse)this.getResponse(this.client, request);
      AlipayF2FPayResult result = new AlipayF2FPayResult(response);
      if(response != null && "10000".equals(response.getCode())) {
         result.setTradeStatus(TradeStatus.SUCCESS);
      } else {
         AlipayTradeQueryResponse queryResponse;
         if(response != null && "10003".equals(response.getCode())) {
            queryResponse = this.loopQueryResult(outTradeNo);
            return this.checkQueryAndCancel(outTradeNo, result, queryResponse);
         }

         if(this.tradeError(response)) {
            queryResponse = this.tradeQuery(outTradeNo);
            return this.checkQueryAndCancel(outTradeNo, result, queryResponse);
         }

         result.setTradeStatus(TradeStatus.FAILED);
      }

      return result;
   }

   private AlipayF2FPayResult checkQueryAndCancel(String outTradeNo, AlipayF2FPayResult result, AlipayTradeQueryResponse queryResponse) {
      if(this.querySuccess(queryResponse)) {
         result.setTradeStatus(TradeStatus.SUCCESS);
         result.setResponse(this.toPayResponse(queryResponse));
         return result;
      } else {
         AlipayTradeCancelResponse cancelResponse = this.cancelPayResult(outTradeNo);
         if(this.tradeError(cancelResponse)) {
            result.setTradeStatus(TradeStatus.UNKNOWN);
         } else {
            result.setTradeStatus(TradeStatus.FAILED);
         }

         return result;
      }
   }

   public static class ClientBuilder {

      private String gatewayUrl;
      private String appid;
      private String privateKey;
      private String format;
      private String charset;
      private String alipayPublicKey;


      public AlipayTradeServiceImpl build() {
         if(StringUtils.isEmpty(this.gatewayUrl)) {
            this.gatewayUrl = Configs.getOpenApiDomain();
         }

         if(StringUtils.isEmpty(this.appid)) {
            this.appid = Configs.getAppid();
         }

         if(StringUtils.isEmpty(this.privateKey)) {
            this.privateKey = Configs.getPrivateKey();
         }

         if(StringUtils.isEmpty(this.format)) {
            this.format = "json";
         }

         if(StringUtils.isEmpty(this.charset)) {
            this.charset = "utf-8";
         }

         if(StringUtils.isEmpty(this.alipayPublicKey)) {
            this.alipayPublicKey = Configs.getAlipayPublicKey();
         }

         return new AlipayTradeServiceImpl(this);
      }

      public AlipayTradeServiceImpl.ClientBuilder setAlipayPublicKey(String alipayPublicKey) {
         this.alipayPublicKey = alipayPublicKey;
         return this;
      }

      public AlipayTradeServiceImpl.ClientBuilder setAppid(String appid) {
         this.appid = appid;
         return this;
      }

      public AlipayTradeServiceImpl.ClientBuilder setCharset(String charset) {
         this.charset = charset;
         return this;
      }

      public AlipayTradeServiceImpl.ClientBuilder setFormat(String format) {
         this.format = format;
         return this;
      }

      public AlipayTradeServiceImpl.ClientBuilder setGatewayUrl(String gatewayUrl) {
         this.gatewayUrl = gatewayUrl;
         return this;
      }

      public AlipayTradeServiceImpl.ClientBuilder setPrivateKey(String privateKey) {
         this.privateKey = privateKey;
         return this;
      }

      public String getAlipayPublicKey() {
         return this.alipayPublicKey;
      }

      public String getAppid() {
         return this.appid;
      }

      public String getCharset() {
         return this.charset;
      }

      public String getFormat() {
         return this.format;
      }

      public String getGatewayUrl() {
         return this.gatewayUrl;
      }

      public String getPrivateKey() {
         return this.privateKey;
      }
   }
}
